#include "RectScript.h"
#include "clazz.h"
#include <Windows.h>
#include <gdiplus.h>

using namespace Gdiplus;

#define Push_REAL(L,n) lua_pushnumber(L,(double)n)
#define Get_REAL(L,idx) (float)lua_tonumber(L,idx)
#define Set_REAL EQUAL

#define Push_int lua_pushinteger
#define Get_int lua_tointeger
#define Set_int EQUAL

SGField(SizeF,Width,REAL);
SGField(SizeF,Height,REAL);

SGField(PointF,X,REAL);
SGField(PointF,Y,REAL);

SGField(RectF,Width,REAL);
SGField(RectF,Height,REAL);
SGField(RectF,Y,REAL);
SGField(RectF,X,REAL);

SGField(POINT,x,int);
SGField(POINT,y,int);

static int Size_init(lua_State *L);
static int Size_release(lua_State *L);
static int Size_tostring(lua_State *L);

static int Point_init(lua_State *L);
static int Point_release(lua_State *L);
static int Point_tostring(lua_State *L);

static int POINT_init(lua_State *L);
static int POINT_release(lua_State *L);
static int POINT_tostring(lua_State *L);

static int Rect_init(lua_State *L);
static int Rect_release(lua_State *L);
static int Rect_tostring(lua_State *L);

static int Color_init(lua_State *L);
static int Color_release(lua_State *L);
static int Color_tostring(lua_State *L);

int lua_openrect(lua_State *L){
	BeginEnum(L,"FontStyle");
	EnumNameValue(L,"FontStyleRegular",Gdiplus::FontStyleRegular);
	EnumNameValue(L,"FontStyleBold",Gdiplus::FontStyleBold);
	EnumNameValue(L,"FontStyleItalic",Gdiplus::FontStyleItalic);
	EnumNameValue(L,"FontStyleBoldItalic",Gdiplus::FontStyleBoldItalic);
	EnumNameValue(L,"FontStyleUnderline",Gdiplus::FontStyleUnderline);
	EnumNameValue(L,"FontStyleStrikeout",Gdiplus::FontStyleStrikeout);
	EndEnum(L);

	BeginEnum(L,"StringAlignment");
	EnumNameValue(L,"StringAlignmentNear",Gdiplus::StringAlignmentNear);
	EnumNameValue(L,"StringAlignmentCenter",Gdiplus::StringAlignmentCenter);
	EnumNameValue(L,"StringAlignmentFar",Gdiplus::StringAlignmentFar);
	EndEnum(L);

	BeginModule(L,"Color");
	InitModule(L,Color_init,Color_release);
	ModuleToString(L,Color_tostring);
	EndModule(L);

	BeginModule(L,"Size");
	InitModule(L,Size_init,Size_release);
	ModuleField(L,"Width",Getter(SizeF,Width),Setter(SizeF,Width));
	ModuleField(L,"Height",Getter(SizeF,Height),Setter(SizeF,Height));
	ModuleToString(L,Size_tostring);
	EndModule(L);

	BeginModule(L,"Point");
	InitModule(L,Point_init,Point_release);
	ModuleField(L,"X",Getter(PointF,X),Setter(PointF,X));
	ModuleField(L,"Y",Getter(PointF,Y),Setter(PointF,Y));
	ModuleToString(L,Point_tostring);
	EndModule(L);

	BeginModule(L,"Rect");
	InitModule(L,Rect_init,Rect_release);
	ModuleField(L,"X",Getter(RectF,X),Setter(RectF,X));
	ModuleField(L,"Y",Getter(RectF,Y),Setter(RectF,Y));
	ModuleField(L,"Width",Getter(RectF,Width),Setter(RectF,Width));
	ModuleField(L,"Height",Getter(RectF,Height),Setter(RectF,Height));
	ModuleToString(L,Rect_tostring);
	EndModule(L);

	BeginModule(L,"POINT");
	InitModule(L,POINT_init,POINT_release);
	ModuleField(L,"x",Getter(POINT,x),Setter(POINT,x));
	ModuleField(L,"y",Getter(POINT,y),Setter(POINT,y));
	ModuleToString(L,POINT_tostring);
	EndModule(L);
	return 0;
}


int lua_closerect(lua_State *L){
	lua_pushnil(L);
	lua_setglobal(L,"FontStyle");
	lua_pushnil(L);
	lua_setglobal(L,"Color");
	lua_pushnil(L);
	lua_setglobal(L,"Size");
	lua_pushnil(L);
	lua_setglobal(L,"Point");
	lua_pushnil(L);
	lua_setglobal(L,"Rect");
	lua_pushnil(L);
	lua_setglobal(L,"POINT");
	lua_pushnil(L);
	lua_setglobal(L,"StringAlignment");
	return 0;
}

int Size_init(lua_State *L){
	REAL w = lua_tonumber(L,1);
	REAL h = lua_tonumber(L,2);
	pushuserdata(L,new SizeF(w,h),true);
	return 1;
}

int Size_release(lua_State *L){
	void *p = (void *)touserdata(L,1);
	if(p){
		delete (SizeF *)p;
	}
	return 0;
}

int Point_init(lua_State *L){
	REAL x = lua_tonumber(L,1);
	REAL y = lua_tonumber(L,2);
	pushuserdata(L, new PointF(x,y),true);
	return 1;
}

int Point_release(lua_State *L){
	void *p = touserdata(L,1);
	if(p){
		delete (PointF *)p;
	}
	return 0;
}

int Rect_init(lua_State *L){
	REAL x = lua_tonumber(L,1);
	REAL y = lua_tonumber(L,2);
	REAL width = lua_tonumber(L,3);
	REAL height = lua_tonumber(L,4);
	pushuserdata(L,new RectF(x,y,width,height),true);
	return 1;
}

int Rect_release(lua_State *L){
	void * p = touserdata(L,1);
	if(p){
		delete (RectF *)p;
	}
	return 0;
}

int POINT_init(lua_State *L){
	int x = lua_tointeger(L,1);
	int y = lua_tointeger(L,2);
	POINT *pnt = new POINT();
	pnt->x = x;
	pnt->y = y;
	pushuserdata(L, pnt,true);
	return 1;
}

int POINT_tostring(lua_State *L){
	char temp_string[128];
	POINT *pnt = (POINT *)ModuleCheck(L,1,"POINT");
	sprintf(temp_string,"POINT:(%d,%d)",pnt->x,pnt->y);
	return 1;
}

int POINT_release(lua_State *L){
	void *p = touserdata(L,1);
	if(p){
		delete (POINT *)p;
	}
	return 0;
}


int Color_init(lua_State *L){
	int top =lua_gettop(L);
	Gdiplus::Color * color = 0;
	if(top == 1){
		color = new Gdiplus::Color();
		color->SetValue((Gdiplus::ARGB)luaL_checkinteger(L,1));
	}else if(top == 3){
		color = new Gdiplus::Color(
			(BYTE)luaL_checkinteger(L,1),
			(BYTE)luaL_checkinteger(L,2),
			(BYTE)luaL_checkinteger(L,3)
		);
	}else if(top == 4){	
		color = new Gdiplus::Color(
			(BYTE)luaL_checkinteger(L,1),
			(BYTE)luaL_checkinteger(L,2),
			(BYTE)luaL_checkinteger(L,3),
			(BYTE)luaL_checkinteger(L,4)
		);
	}
	pushuserdata(L,color,true);
	return 1;
}

int Color_release(lua_State *L){
	Gdiplus::Color * color = (Gdiplus::Color *)touserdata(L,1);
	if(color){
		delete color;
	}
	return 0;
}

int Color_tostring(lua_State *L){
	char temp_string[128];
	Gdiplus::Color * color = (Gdiplus::Color *)touserdata(L,1);
	sprintf(temp_string,"Color:0x%x",color->GetValue());
	lua_pushstring(L,temp_string);
	return 1;
}

int Size_tostring(lua_State *L){
	char temp_string[128];
	Gdiplus::SizeF * sz = (Gdiplus::SizeF *)touserdata(L,1);
	sprintf(temp_string,"Size:(%0.2f,%0.2f)",sz->Width,sz->Height);
	lua_pushstring(L,temp_string);
	return 1;
}

int Point_tostring(lua_State *L){
	char temp_string[128];
	Gdiplus::PointF * pnt = (Gdiplus::PointF *)touserdata(L,1);
	sprintf(temp_string,"Point:(%0.2f,%0.2f)",pnt->X,pnt->Y);
	lua_pushstring(L,temp_string);
	return 1;
}

int Rect_tostring(lua_State *L){
	char temp_string[128];
	Gdiplus::RectF * rect = (Gdiplus::RectF *)touserdata(L,1);
	sprintf(temp_string,"Rect:(%0.2f,%0.2f,%0.2f,%0.2f)",rect->X,rect->Y,rect->Width,rect->Height);
	lua_pushstring(L,temp_string);
	return 1;
}
